/* 
    file:   ui_core.c
 */
/* ------------------------------------------------------------------------- */
#include "ui_core.h"
#include "stdlib.h"

#define     DEBUGPRINTEN        0

#if DEBUGPRINTEN
#include "stdio.h"
#endif
#define null 0


/* blend tools*/
uint16_t    AlphaColor565(uint16_t cla,uint16_t clb,uint8_t alpha)
{
    uint16_t ar,ag,ab;
    uint16_t br,bg,bb;
    uint16_t cr,cg,cb;

    if(alpha==0xff)
    {
        return cla;
    }
    if(alpha==0x00)
    {
        return clb;
    }

    ar = (cla&0xf800)>>8;
    ag = (cla&0x7e0)>>3;
    ab = (cla&0x1f)<<3;

    br = (clb&0xf800)>>8;
    bg = (clb&0x7e0)>>3;
    bb = (clb&0x1f)<<3;

    cr = ((alpha)*ar+(0xff-alpha)*br)>>8;
    cg = ((alpha)*ag+(0xff-alpha)*bg)>>8;
    cb = ((alpha)*ab+(0xff-alpha)*bb)>>8;

    return RGB888T565(cr,cg,cb);
}


/* memory fill tool */
void ui_memfill(void * pdat,unsigned char dc,uint32_t len)
{
    uint32_t i;
    uint8_t * pdatt = pdat;
    for ( i = 0; i < len; i++)
    {
        pdatt[i] = dc;
    }
}

/* ui_int_limit */
int ui_int_limit(int din,int num1,int num2)
{
    if(num1>num2)
    {
        if(din>num1){return num1;}
        if(din<num2){return num2;}
    }
    else
    {
        if(din>num2){return num2;}
        if(din<num1){return num1;}
    }
    return din;
}

/* set obj position */
void ui_obj_set_pos(struct ui_obj * pobj,uint32_t px,uint32_t py)
{
    uint32_t sx,sy;
    sx = pobj->area.x2-pobj->area.x1;
    sy = pobj->area.y2-pobj->area.y1;
    pobj->area.x1 = px;
    pobj->area.y1 = py;
    pobj->area.x2 = px + sx;
    pobj->area.y2 = py + sy;
}

uint8_t pointinarea(ui_area * pa,point * np)
{
    uint8_t flagx = 0;
    uint8_t flagy = 0;

    if(((pa->x2)>(np->x))&&((pa->x1)<(np->x)))
    {
        flagx = 1;
    }

    if(((pa->y2)>(np->y))&&((pa->y1)<(np->y)))
    {
        flagy = 1;
    }

    if(flagy&&flagx)
    {
        return 1;
    }

    return 0;
}

/* add new ll */
struct ui_obj * ui_newobj(struct ui_obj * ppar)
{
    struct ui_obj * newlinkls = null;

    /* [0] get memory for new obj */
    newlinkls = (struct ui_obj *)ui_malloc(sizeof(struct ui_obj));
#if DEBUGPRINTEN
    printf("malloc add      [%x]\r\n",newlinkls);
#endif

    /* [1] init new obj */
    if(newlinkls)
    {
        newlinkls->par = NULL;
        newlinkls->item = NULL;
        newlinkls->pre = NULL;
        newlinkls->next = NULL;
        newlinkls->area.x1 = 0;
        newlinkls->area.y1 = 0;
        newlinkls->area.x2 = 0;
        newlinkls->area.y2 = 0;
        newlinkls->objdat = NULL;
        newlinkls->style_p = NULL;

        newlinkls->event_cb = NULL;
        newlinkls->signal_cb = NULL;
        newlinkls->design_cb = NULL;
        newlinkls->status = 0;
        newlinkls->touch = 0;
        newlinkls->hiden = 0;
        newlinkls->pudata = NULL;

        if(ppar)
        {
            if((ppar->item) != null)
            {
                // newlinkls->pre = null;          
                newlinkls->next = (ppar->item); //set new obj's next
                newlinkls->par = ppar;          //set new obj's par
                (ppar->item)->pre = newlinkls;  //set next obj's pre

                (ppar->item) = newlinkls;       //set new to first
            }
            else
            {
                if(newlinkls != null)
                {
                    // newlinkls->pre = null;
                    newlinkls->next = null;
                    newlinkls->par = ppar;
                    (ppar->item) = newlinkls;
                }
            }
        }
    }
    else
    {
        return null;
    }
    return newlinkls;
}
void ui_objseteventcb(struct ui_obj *objs,ui_event_cb_t eventcb)
{
    objs->event_cb = eventcb;
}
/* delete all ll */
void ui_delobj(struct ui_obj * ptg)
{
    struct ui_obj * nextptg = null;
    struct ui_obj * ptgwd = ptg;

    while(ptgwd)
    {
        /* 处理附属控件 */
        if(ptgwd->item)
        {
#if DEBUGPRINTEN
            printf("item del start [%x]-----------------\r\n",ptgwd->item);
#endif
            ui_delobj(ptgwd->item);
#if DEBUGPRINTEN
            printf("item del end   [%x]-----------------\r\n",ptgwd->item);
#endif
        }
        
        nextptg = ptgwd->next;
        /* 处理附属数据 */
        if(ptgwd->objdat)
        {
            ui_free(ptgwd->objdat);
            //ui_free(tlsf_guipool,ptgwd->objdat);
            //free(ptgwd->objdat);
#if DEBUGPRINTEN
            printf("free data      [%x]\r\n",ptgwd->objdat);
#endif
            ptgwd->objdat = null;
        }

        /* 删除当前 */
        //free(ptgwd);
        //ui_free(tlsf_guipool,ptgwd);
        ui_free(ptgwd);
#if DEBUGPRINTEN
        printf("free obj       [%x]\r\n",ptgwd);
#endif
        /* 更改下一个为当前 */
        
        ptgwd = nextptg;
    }
}

void ui_getlct(struct ui_obj *objs,  point * ppnt)
{
    int lx = 0;
    int ly = 0;
    struct ui_obj * nextptg = NULL;
    struct ui_obj * ptgwd = objs;
    while (ptgwd)
    {
        lx+=ptgwd->area.x1;
        ly+=ptgwd->area.y1;

        nextptg = ptgwd->par;
        ptgwd = nextptg;
    }
    if(ppnt)
    {
        ppnt->x = lx;
        ppnt->y = ly;
    }
}

void ui_objredraw(struct ui_obj *objs,void *param)
{
    struct ui_obj * nextptg = NULL;
    struct ui_obj * ptgwd = objs;

    while(ptgwd)
    {
        /* 先显示自己 */
        if(ptgwd->signal_cb)
        {
            ptgwd->signal_cb(ptgwd,ui_signal_init_r,param);
            ptgwd->status = 1;
        }
        /* 如果有附属控件显示控件 */
        if(ptgwd->item)
        {
            ui_objredraw(ptgwd->item,param);//嵌套调用
        }
        
        nextptg = ptgwd->next;
        ptgwd = nextptg;
    }
}

uint8_t ui_objsign(struct ui_obj *objs,  point * ppnt,uint8_t sign,struct ui_core * param)
{
    struct ui_obj * nextptg = NULL;
    struct ui_obj * ptgwd = objs;
    point  reallct;
    ui_area realarea;

    uint8_t tagetstatus = 1;
    while(ptgwd)
    {
        /* 如果有附属控件，检查坐标是否在附属控件中 */
        if(ptgwd->item)
        {
            ui_objsign(ptgwd->item,ppnt,sign,param);
        }
        /* 检查本当前控件是否包含坐标 */
        if(ptgwd->touch)
        {
            ui_getlct(ptgwd,&reallct);//计算真实坐标位置
            realarea.x1 =reallct.x;
            realarea.x2 =reallct.x+ptgwd->area.x2-ptgwd->area.x1;
            realarea.y1 =reallct.y;
            realarea.y2 =reallct.y+ptgwd->area.y2-ptgwd->area.y1;
            //realarea = ptgwd->rarea;
            if(pointinarea(&realarea,ppnt))
            {
                if(sign != ui_signal_pressing)
                {
                    if(ptgwd->event_cb)
                    {
                        ptgwd->event_cb(ptgwd,sign);
                    }
                }
                if((sign == ui_signal_pressed)|(sign == ui_signal_pressing))
                {
                    tagetstatus = 2;
                }
                else
                {
                    tagetstatus = 1;
                }
                if(ptgwd->status != tagetstatus)
                {
                    if(ptgwd->signal_cb)
                    {
                        if(param)
                        {
                            
                            ui_disp_copy(param->pscr->pbfa,\
                                            realarea.x1,realarea.y1,\
                                            realarea.x2,realarea.y2,\
                                            param->pscr->pbfb,param->pscr->width);
                            ptgwd->signal_cb(ptgwd,sign,param);
                            if(ptgwd->item)
                            {
                                ui_objredraw(ptgwd->item,param);
                            }
                            param->pscr->printer(realarea.x1,realarea.y1,\
                                            realarea.x2,realarea.y2,\
                                            param->pscr->pbfb);
                            //LTDC_Img_CopyToDramEx(realarea.x1,realarea.y1,realarea.x2,realarea.y2,param->pscr->pbfa);
                            //DMA2D_copy(ltdc_lcd_framebuf,realarea.x1,realarea.y1,realarea.x2,realarea.y2,puicore->pscr->pbfa,LCD_WIDTH);
                        }
                    }
                }
                ptgwd->status = tagetstatus;
                //return 1;
            }
            else
            {
                //检查触控点是否离开
                if(ptgwd->status != 1)
                {
                    if(ptgwd->signal_cb)
                    {
                        if(param)
                        {
                            ui_disp_copy(param->pscr->pbfa,\
                                            realarea.x1,realarea.y1,\
                                            realarea.x2,realarea.y2,\
                                            param->pscr->pbfb,param->pscr->width);
                            ptgwd->signal_cb(ptgwd,ui_signal_releassed,param);
                            if(ptgwd->item)
                            {
                                ui_objredraw(ptgwd->item,param);
                            }
                            param->pscr->printer(realarea.x1,realarea.y1,\
                                            realarea.x2,realarea.y2,\
                                            param->pscr->pbfb);
                            //LTDC_Img_CopyToDramEx(realarea.x1,realarea.y1,realarea.x2,realarea.y2,puicore->pscr->pbfa);
                            //DMA2D_copy(ltdc_lcd_framebuf,realarea.x1,realarea.y1,realarea.x2,realarea.y2,puicore->pscr->pbfa,LCD_WIDTH);
                        }
                    }
                    ptgwd->status = 1;
                }
            }
        }

        nextptg = ptgwd->next;
        ptgwd = nextptg;
    }
	return 0;
}
uint8_t ui_objreflash(struct ui_obj *objs,struct ui_core * param)
{
    struct ui_obj * nextptg = NULL;
    struct ui_obj * ptgwd = objs;
    point  reallct;
    ui_area realarea;
    while(ptgwd)
    {
        /* 如果有附属控件，检查坐标是否在附属控件中 */
        if(ptgwd->item)
        {
            ui_objreflash(ptgwd->item,param);
        }

        //检查触控点是否离开
        if(ptgwd->status > 1)
        {
            ui_getlct(ptgwd,&reallct);
            realarea.x1 =reallct.x;
            realarea.x2 =reallct.x+ptgwd->area.x2-ptgwd->area.x1;
            realarea.y1 =reallct.y;
            realarea.y2 =reallct.y+ptgwd->area.y2-ptgwd->area.y1;
            //realarea = ptgwd->rarea;
            struct ui_core * puicore = NULL;
            if(param)
            {
                ui_disp_copy(param->pscr->pbfa,\
                                            realarea.x1,realarea.y1,\
                                            realarea.x2,realarea.y2,\
                                            param->pscr->pbfb,param->pscr->width);
                
                ui_objredraw(ptgwd,param);
                param->pscr->printer(realarea.x1,realarea.y1,\
                                            realarea.x2,realarea.y2,\
                                            param->pscr->pbfb);

            }

            ptgwd->status = 1;
        }

        
        nextptg = ptgwd->next;
        ptgwd = nextptg;
    }
	return 0;
}



void ui_objdesign(struct ui_obj *objs,void * param)
{
    struct ui_obj * nextptg = NULL;
    struct ui_obj * ptgwd = objs;
    point  reallct;
    ui_area realarea;
    while(ptgwd)
    {
        /* 检查本当前控件是否包含坐标 */
        ui_getlct(ptgwd,&reallct);
        //realarea = ptgwd->area;
        realarea.x1 =reallct.x;
        realarea.x2 =reallct.x+ptgwd->area.x2-ptgwd->area.x1;
        realarea.y1 =reallct.y;
        realarea.y2 =reallct.y+ptgwd->area.y2-ptgwd->area.y1;

        if(ptgwd->touch)
        {
            break;
        }
        if(ptgwd->signal_cb)
        {
            ptgwd->signal_cb(ptgwd,ui_signal_init,param);
        }
        ptgwd->status = 1;

        /* 如果有附属控件，检查坐标是否在附属控件中 */
        if(ptgwd->item)
        {
            ui_objdesign(ptgwd->item,param);//嵌套调用
        }
        
        nextptg = ptgwd->next;
        ptgwd = nextptg;
    } 
}

void ui_objinsign(struct ui_obj *objs,void * param)
{
    struct ui_obj * nextptg = NULL;
    struct ui_obj * ptgwd = objs;
    point  reallct;
    ui_area realarea;
    while(ptgwd)
    {
        /* 检查本当前控件是否包含坐标 */
        ui_getlct(ptgwd,&reallct);
        //realarea = ptgwd->area;
        realarea.x1 =reallct.x;
        realarea.x2 =reallct.x+ptgwd->area.x2-ptgwd->area.x1;
        realarea.y1 =reallct.y;
        realarea.y2 =reallct.y+ptgwd->area.y2-ptgwd->area.y1;

        if(ptgwd->signal_cb)
        {
            ptgwd->signal_cb(ptgwd,ui_signal_init_r,param);
        }
        ptgwd->status = 1;

        /* 如果有附属控件，检查坐标是否在附属控件中 */
        if(ptgwd->item)
        {   
            ui_objinsign(ptgwd->item,param);//嵌套调用
        }
        
        nextptg = ptgwd->next;
        ptgwd = nextptg;
    } 
}

void ui_run(struct ui_core * pcore,struct ui_obj *objs)
{
    uint32_t idxt;
    point np;

    /* [0]reflash objs */
    if(!pcore->status)
    {
        pcore->status = 1;
        //清屏
        ui_disp_fill(pcore->pscr->pbfb,0,0,pcore->pscr->width-1,pcore->pscr->heigh-1,0x0000);
        ui_objdesign(objs,pcore);//绘制背景
        if((pcore->pscr->pbfb)&&(pcore->pscr->pbfa))
        {
        //    LTDC_Color_Fill(pcore->pscr->pbfa,\
        //                    0,0,pcore->pscr->width-1,pcore->pscr->heigh-1,\
        //                    pcore->pscr->pbfb);
            ui_disp_copy(pcore->pscr->pbfa,\
                            0,0,pcore->pscr->width-1,pcore->pscr->heigh-1,
                            pcore->pscr->pbfb,pcore->pscr->width);
        }
        ui_objinsign(objs,pcore);//绘制动态控件默认状态
        if((pcore->pscr->printer)&&(pcore->pscr->pbfb)&&(pcore->pscr->pbfa))
        {
            pcore->pscr->printer(0,0,pcore->pscr->width-1,pcore->pscr->heigh-1,pcore->pscr->pbfa);
        }
    }

    /* [0]获取输入状态 */
    //触屏输入
    if(pcore->pindev)
    {
        if(pcore->pindev->pgt_cb)
        {
            unsigned int touch_type = pcore->pindev->pgt_cb(&np);
            if(touch_type != ui_signal_none)
            {
                ui_objsign(objs,&np,touch_type,pcore);
            }
            else
            {
                ui_objreflash(objs,pcore);
            }
        }
    }
}

